// benchmark to measure the speed of move generation in KCChess.
// This micro benchmark takes one chess position and 
// simply generates all possible moves up to a give depth. 
// It counts the number of visited nodes and divides by the time used. 


// run:  g++  -DDEBUG=0 -O2 -DHAVE_x86_64_asm move_bench.cc kcchess.cc ; ./a.out <DEPTH>

#include <vector>
#include <cassert>
#include <string>
#include <iostream> 
#include <fstream>
#include <ctime>
using namespace std;

#include "kcchess.h"
using namespace KCChess;

size_t search_bench(const BOARD &board, size_t depth)
{
    size_t res = 1;

    GEN_MOVE_ACTION_STORE pseudo_moves;
    size_t n_pseudo_moves = board.gen_moves(pseudo_moves);
    if(depth > 0){
        for(size_t i = 0; i < n_pseudo_moves; i++){
            MOVE::move_t the_move = pseudo_moves[i];
            BOARD new_board(board, the_move);
            if(new_board.ally_K_is_attacked()) continue;
            new_board.reflect_in_place();
            res += search_bench(new_board, depth - 1);
        }
    }else{
        for(size_t i = 0; i < n_pseudo_moves; i++){
            MOVE::move_t the_move = pseudo_moves[i];
            BOARD new_board(board, the_move);
            if(new_board.ally_K_is_attacked()) continue;
            res++;
        }

    }
    return res;
}



int main(int argc, char **argv)
{
    BOARD board;
//    board.set_new_game();
    board.read_fen("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq -");
//    board.read_fen("2rr3k/pp3pp1/1nnqbN1p/3pN3/2pP4/2P3Q1/PPB4P/R4RK1 w - -");
//    board.read_fen("8/7p/5k2/5p2/p1p2P2/Pr1pPK2/1P1R3P/8 b - -");
//    board.read_fen("b2b1r1k/3R1ppp/4qP2/4p1PQ/4P3/5B2/4N1K1/8 w - -");
//    board.read_fen("1n2rr2/1pk3pp/pNn2p2/2N1p3/8/6P1/PP2PPKP/2RR4 w - -");
    board.show_board(cout);
    GEN_MOVE_ACTION_STORE pseudo_moves;
    size_t n_pseudo_moves = board.gen_moves(pseudo_moves);
    int n_legal_moves = 0;
    for(size_t i = 0; i < n_pseudo_moves; i++){
        MOVE::move_t the_move = pseudo_moves[i];
        BOARD new_board(board, the_move);
        if(new_board.ally_K_is_attacked()) continue;
        n_legal_moves++;
        cout << MOVE(the_move) << " ";
//        new_board.reflect_in_place();
//        new_board.show_board(cout);
    }
    cout << endl << n_pseudo_moves << " " << n_legal_moves << endl;


    int max_depth = argc == 2 ? atoi(argv[1]) : 5;

    for(int depth = 0; depth <= max_depth; depth++){
        clock_t t = clock();
        size_t n_nodes = search_bench(board, depth);
        t = clock() - t;
        cout 
            << "d="       << depth 
            << "\tn="      << n_nodes
            << "\tt="      << ((double)t / CLOCKS_PER_SEC) 
            << "\tratio="  << ((double)n_nodes * CLOCKS_PER_SEC / t)
            << endl;

    }


}
